﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Windows.Automation;

namespace QuickUIT.Tests
{
    [TestClass]
    public class LocatorParserTest
    {
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetSearchCriteriaShouldThrowArgumentNullExceptionForNullLocator()
        {
            LocatorParser.GetSearchCriteria(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetSearchCriteriaShouldThrowArgumentExceptionForEmptyLocator()
        {
            LocatorParser.GetSearchCriteria(String.Empty); 
        }

        [TestMethod]
        public void GetSearchCriteriaCanGetSinglePropertyConditionFromSingleLocator()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("@AutomationId='TestId'") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(1, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementExactSearchCondition), searchCriteria.Conditions[0].GetType()); 
            var condition = searchCriteria.Conditions[0] as AutomationElementExactSearchCondition;
            Assert.IsNotNull(condition);
            Assert.AreEqual(AutomationElementIdentifiers.AutomationIdProperty, condition.Property);
            Assert.AreEqual("TestId", condition.Value); 
        }
        
        [TestMethod] 
        public void GetSearchCriteriaCanGetPropertyConditionWithEmptyValue()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("@Name=''") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(1, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementExactSearchCondition), searchCriteria.Conditions[0].GetType());
            var condition = searchCriteria.Conditions[0] as AutomationElementExactSearchCondition;
            Assert.IsNotNull(condition);
            Assert.AreEqual(AutomationElementIdentifiers.NameProperty, condition.Property);
            Assert.AreEqual(String.Empty, condition.Value); 
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))] 
        public void GetSearchCriteriaShouldThrowArgumentExceptionForSingleMalformedLocator()
        {
            LocatorParser.GetSearchCriteria("@AutomationId");
        }

        [TestMethod]
        public void GetSearchCriteriaCanGetMultiplePropertyConditions()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("[@AutomationId='textBox'][@Name='test']") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(2, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementExactSearchCondition), searchCriteria.Conditions[0].GetType());
            Assert.AreEqual(typeof(AutomationElementExactSearchCondition), searchCriteria.Conditions[1].GetType());
            var condition1 = searchCriteria.Conditions[0] as AutomationElementExactSearchCondition;
            var condition2 = searchCriteria.Conditions[1] as AutomationElementExactSearchCondition;
            Assert.IsNotNull(condition1);
            Assert.IsNotNull(condition2);
            Assert.AreEqual(AutomationElementIdentifiers.AutomationIdProperty, condition1.Property);
            Assert.AreEqual("textBox", condition1.Value);
            Assert.AreEqual(AutomationElementIdentifiers.NameProperty, condition2.Property);
            Assert.AreEqual("test", condition2.Value);
        }

        [TestMethod]
        public void GetSearchCriteriaCanGetSinglePropertyConditionsWithRegex()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("@AutomationId='/TextBox[0-9]*/'") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(1, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementRegexSearchCondition), searchCriteria.Conditions[0].GetType());
            var condition = searchCriteria.Conditions[0] as AutomationElementRegexSearchCondition;
            Assert.IsNotNull(condition);
            Assert.AreEqual(AutomationElementIdentifiers.AutomationIdProperty, condition.Property);
        }

        [TestMethod]
        public void GetSearchCriteriaCanGetMultiplePropertyConditionsWithRegex()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("[@AutomationId='/TextBox[0-9]*/'][@Name='test']") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria); 
            Assert.AreEqual(2, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementRegexSearchCondition), searchCriteria.Conditions[0].GetType());
            Assert.AreEqual(typeof(AutomationElementExactSearchCondition), searchCriteria.Conditions[1].GetType());
            var condition1 = searchCriteria.Conditions[0] as AutomationElementRegexSearchCondition;
            var condition2 = searchCriteria.Conditions[1] as AutomationElementExactSearchCondition;
            Assert.IsNotNull(condition1);
            Assert.IsNotNull(condition2);
            Assert.AreEqual(AutomationElementIdentifiers.AutomationIdProperty, condition1.Property);
            Assert.AreEqual(AutomationElementIdentifiers.NameProperty, condition2.Property);
            Assert.AreEqual("test", condition2.Value);
        }

        [TestMethod] 
        public void GetSearchCriteriaCanGetSinglePropertyConditionsWithContains()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("@AutomationId='{contains}'") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(1, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementContainsSearchCondition), searchCriteria.Conditions[0].GetType());
            var condition = searchCriteria.Conditions[0] as AutomationElementContainsSearchCondition;
            Assert.IsNotNull(condition);
            Assert.AreEqual(AutomationElementIdentifiers.AutomationIdProperty, condition.Property);
            Assert.AreEqual("contains", condition.Value);
        }

        [TestMethod]
        public void GetSearchCriteriaCanGetMultiplePropertyConditionsWithContains()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("[@AutomationId='/TextBox[0-9]*/'][@Name='{test}']") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(2, searchCriteria.Conditions.Count);
            Assert.AreEqual(typeof(AutomationElementRegexSearchCondition), searchCriteria.Conditions[0].GetType());
            Assert.AreEqual(typeof(AutomationElementContainsSearchCondition), searchCriteria.Conditions[1].GetType());
            var condition1 = searchCriteria.Conditions[0] as AutomationElementRegexSearchCondition;
            var condition2 = searchCriteria.Conditions[1] as AutomationElementContainsSearchCondition;
            Assert.IsNotNull(condition1);
            Assert.IsNotNull(condition2);
            Assert.AreEqual(AutomationElementIdentifiers.AutomationIdProperty, condition1.Property);
            Assert.AreEqual(AutomationElementIdentifiers.NameProperty, condition2.Property);
            Assert.AreEqual("test", condition2.Value);
        }

        [TestMethod]
        public void ShouldGetDefaultIndex()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("[@AutomationId='Test']") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(1, searchCriteria.Conditions.Count);
            Assert.AreEqual(-1, searchCriteria.Index);
        }

        [TestMethod]
        public void ShouldGetIndex()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("[1]") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(0, searchCriteria.Conditions.Count);
            Assert.AreEqual(1, searchCriteria.Index);
        }

        [TestMethod]
        public void ShouldGetIndexAndSearchConditions()
        {
            var searchCriteria = LocatorParser.GetSearchCriteria("[@AutomationId='Test'][0]") as AutomationElementSearchCriteria;
            Assert.IsNotNull(searchCriteria);
            Assert.AreEqual(1, searchCriteria.Conditions.Count);
            Assert.AreEqual(0, searchCriteria.Index);
        }
    }
}
